#include "vo.h"

VO::VO(QWidget *parent) :
	QMainWindow(parent), filtroVentana(this) {

	ui.setupUi(this);
	contador = 0;
	connect(&filtroVentana, SIGNAL(signalAplicar()), this, SLOT(aplicarFiltro()));
}

VO::~VO() {

}

void VO::open() {
	QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
			QDir::currentPath() + "/pruebas");
	if (!fileName.isEmpty()) {
		try {
			Imagen * img = new Imagen(this, fileName);
			addImage(img);
		} catch (QString msg) {
			QMessageBox::information(this, tr("Error"), msg);
		}
	}
}

void VO::save() {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			actual->getImagen()->save();
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}
}

VentanaImagen * VO::addImage(Imagen * imagen) {
	contador++;
	VentanaImagen *wid = new VentanaImagen(imagen);
	ui.mdiArea->addSubWindow(wid);
	wid->show();
	connect(imagen, SIGNAL(movido(QPoint, QRgb)), this, SLOT(showMovido(QPoint, QRgb)));
	return wid;
}

void VO::showMovido(QPoint punto, QRgb color) {
	ui.statusbar->showMessage(tr("x: %1 , y:%2 | R:%3 , G:%4, B:%5").arg(
			punto.x()).arg(punto.y()).arg(qRed(color)).arg(qGreen(color)).arg(
			qBlue(color)));
}

void VO::nuevaDesdeSeleccion() {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			Imagen * nueva = new Imagen(actual->getImagen()->subImagen(),
					QString::number(contador));
			addImage(nueva);
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}
}

void VO::toGray(double r, double g, double b) {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			actual->getImagen()->toGray(r, g, b);
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}

}

void VO::toGrayPAL() {
	toGray(0.222, 0.707, 0.71);
}

void VO::toGrayNTSC() {
	toGray(0.299, 0.587, 0.114);
}

void VO::undo() {
	VentanaImagen * actual = (VentanaImagen *) ui.mdiArea->activeSubWindow();
	if (actual != NULL) {
		actual->getImagen()->undo();
	}
}

void VO::info() {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			InfoDialog dialog(actual->getImagen(), this);
			dialog.exec();
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}

}

void VO::histograma() {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			crearDialogo(actual->getImagen()->pintarHistograma(), tr(
					"Histograma : %1").arg(actual->getImagen()->getTitle()));
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}

}

void VO::histogramaA() {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			crearDialogo(actual->getImagen()->pintarHistogramaA(), tr(
					"Histograma acumulado: %1").arg(
					actual->getImagen()->getTitle()));
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}

}

void VO::transLineal() {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			TransLineal trans(this);
			if (trans.exec()) {
				//for (int i = 0; i < 256; i++) {
				//cout << tabla[i]<< endl;
				//}
				Imagen * nueva = new Imagen(
						actual->getImagen()->transformacionLineal(
								trans.getLineas()), QString::number(contador));
				addImage(nueva);
			}
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}

}

void VO::setBrilloContraste() {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			Imagen * nueva = new Imagen(actual->getImagen()->getImagen(),
					QString::number(contador));
			actual = addImage(nueva);
			double brillo, contraste;
			nueva->getBrilloContraste(brillo, contraste);
			SetBrilloContraste sbc(brillo, contraste);
			connect(&sbc, SIGNAL(actualizar(double, double)), nueva, SLOT(actualizarBrilloContraste(double, double)));
			if (!sbc.exec()) {
				//Restaurar el original
				actual->close();
			}
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}

}

void VO::ecualizar() {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			Imagen * nueva = new Imagen(actual->getImagen()->ecualizar(),
					QString::number(contador));
			addImage(nueva);
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}
}

void VO::digitalizar() {

	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			Digitalizar digitalizar(this);
			if (digitalizar.exec()) {
				Imagen * nueva = new Imagen((actual->getImagen()->digitalizar(
						digitalizar.getTam())), QString::number(contador));
				addImage(nueva);
			}
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}

}

void VO::cuantizar() {

	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			Cuantizar cuantizar(this);
			if (cuantizar.exec()) {
				Imagen * nueva = new Imagen((actual->getImagen()->cuantizar(
						cuantizar.getBits())), QString::number(contador));
				addImage(nueva);
			}
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}

}

void VO::logaritmo() {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			Logaritmo log(this);
			if (log.exec()) {
				Imagen * nueva = new Imagen(actual->getImagen()->logaritmo(
						log.getNumFunc(), log.getK()),
						QString::number(contador));
				addImage(nueva);
			}
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}

}

void VO::exponencial() {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			Logaritmo log(this);
			if (log.exec()) {
				Imagen * nueva = new Imagen(actual->getImagen()->exponencial(
						log.getNumFunc(), log.getK()),
						QString::number(contador));
				addImage(nueva);
			}
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}

}
void VO::perfil() {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			Perfil * perfil = new Perfil(actual->getImagen(), this);
			connect(actual->getImagen(), SIGNAL(finLinea(QPoint, QPoint)), perfil, SLOT(recibirDeImagen(QPoint, QPoint)));
			perfil->show();
			if (perfil->exec()) {
				int x1 = perfil->getX1();
				int x2 = perfil->getX2();
				int y1 = perfil->getY1();
				int y2 = perfil->getY2();

				QWidget * graficas[4];
				actual->getImagen()->perfil(graficas, x1, y1, x2, y2);
				PerfilResultado * resultado = new PerfilResultado(graficas,
						this);
				resultado->show();
			}
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}
}

void VO::vecindad() {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			Vecindad vecindad(actual->getImagen(), this);
			vecindad.exec();
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}
}

void VO::diferencia() {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			QStringList lista;
			QList<int> listaIndices;
			QList<QMdiSubWindow *> listaVentanas = ui.mdiArea->subWindowList();
			QList<QMdiSubWindow *>::iterator i;

			int index = 0;
			VentanaImagen * evaluando;
			for (i = listaVentanas.begin(); i != listaVentanas.end(); ++i) {
				evaluando = (VentanaImagen *) (*i);

				//Si no es la ventana que ya está seleccionada
				if (evaluando != actual) {
					if (evaluando->getImagen()->getSize()
							== actual->getImagen()->getSize()) {
						lista.push_back(evaluando->getImagen()->getTitle());
						listaIndices.push_back(index);
					}
				}
				index++;
			}

			if (listaIndices.size() > 0) {
				SeleccionMultiple sm(lista, this);
				if (sm.exec()) {
					VentanaImagen * seleccionada =
							(VentanaImagen*) listaVentanas.takeAt(
									listaIndices.takeAt(sm.getActive()));
					Imagen * nueva = new Imagen(
							actual->getImagen()->diferencia(
									seleccionada->getImagen()->getImagen(),
									sm.getFactor()), QString::number(contador));
					addImage(nueva);
				}
			} else {
				throw QString::fromUtf8(
						"No hay imágenes del mismo tamaño para comparar.");
			}
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}
}

void VO::espHisto() {

	//ESTO ESTA FATAL HAY QUE ARREGLARLO, FATALLLLLLLL
	//MUCHA LISTA PARA LO MISMO
	//NO USAR LISTAS SINO ARRAYS Y
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();

		if (actual != NULL) {
			QList<QMdiSubWindow *> listaVentanas = ui.mdiArea->subWindowList();
			QStringList lista;
			QList<QMdiSubWindow *> listaSeleccionables;
			QList<QMdiSubWindow *>::iterator i;
			//Recojo los nombres de todas las ventanas
			VentanaImagen * evaluando;
			for (i = listaVentanas.begin(); i != listaVentanas.end(); ++i) {
				evaluando = (VentanaImagen *) (*i);

				//Si no es la ventana que ya está seleccionada
				if (evaluando != actual) {
					lista.push_back(evaluando->getImagen()->getTitle());
					listaSeleccionables.push_back(evaluando);
				}
			}
			SeleccionMultiple sm(lista, this);
			if (sm.exec()) {
				VentanaImagen * seleccionada =
						(VentanaImagen*) listaSeleccionables.takeAt(
								sm.getActive());
				double histogramaANorm2[MAXCOLOR];
				seleccionada->getImagen()->getHistogramaANorm(histogramaANorm2);
				Imagen * nueva = new Imagen(actual->getImagen()->espHisto(
						histogramaANorm2), QString::number(contador));
				addImage(nueva);
			}
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}
}

void VO::crearDialogo(QWidget * widget) {
	crearDialogo(widget, QString(""));
}

void VO::crearDialogo(QWidget * widget, const QString& titulo) {
	QDialog * dialog = new QDialog(this);
	dialog->setAttribute(Qt::WA_DeleteOnClose);
	dialog->setWindowTitle(titulo);
	QVBoxLayout *mainLayout = new QVBoxLayout;
	mainLayout->addWidget(widget);

	dialog->setLayout(mainLayout);
	dialog->show();
}

void VO::negativo() {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			Imagen * nueva = new Imagen(actual->getImagen()->negativo());
			addImage(nueva);
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}

}

void VO::aplicarRuido() {

	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			RuidoVentana ruidoVentana(this);
			if (ruidoVentana.exec()) {
				Imagen * nueva = new Imagen(actual->getImagen()->getQImage(),
						QString::number(contador));
				Imagen * ruido = new Imagen(actual->getImagen()->getQImage(),
						QString(QString::number(contador) + " ruido"));
				switch (ruidoVentana.getCurrentIndex()) {
				case 0: {
					cout << "Entré en ruido impulsivo" << endl;
					nueva->aplicarRuidoImpulsivo(
							ruidoVentana.getPorcentajeImpulsivo(), ruido);
				}
					break;
				case 1: {
					cout << "Entré en ruido uniforme" << endl;
					nueva->aplicarRuidoUniforme(
							ruidoVentana.getPorcentajeUniforme(),
							ruidoVentana.getN1Uniforme(),
							ruidoVentana.getN2Uniforme(), ruido);
				}
					break;
				case 2: {
					cout << "Entré en ruido Guassiano" << endl;
					nueva->aplicarRuidoGaussiano(
							ruidoVentana.getPorcentajeGaussiano(),
							ruidoVentana.getNGaussiano(), ruido);
				}
					break;
				}

				addImage(nueva);
				addImage(ruido);
			}
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}

	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}
}

void VO::filtrar() {
	filtroVentana.show();
}

void VO::aplicarFiltro() {
	VentanaImagen * actual = (VentanaImagen *) ui.mdiArea->activeSubWindow();
	if (actual != NULL) {
		filtroVentana.hide();
		Imagen * nueva = new Imagen(actual->getImagen()->getQImage(),
				QString::number(contador));

		//Obtengo los datos del kernel de filtroVentana para reservar
		//memoria al kernel
		int f, c;
		filtroVentana.getKernelSize(f, c);
		bool separable = filtroVentana.isSeparable();
		int tam;
		if (separable) {
			tam = f + c;
		} else {
			tam = f * c;
		};

		double kernel[tam];
		//Obengo el kernel de filtroVentana
		filtroVentana.getKernel(kernel);
		//Se lo aplico a la imagen
		for (int i = 0; i < tam; i++) {
			cout << "kernel " << kernel[i] << endl;
		}

		//ADAPTAR ESTO PARA QUE ADMITA FILAS Y COLUMNAS
		nueva->aplicarFiltro(kernel, c, f, separable);
		addImage(nueva);
	} else {
		QMessageBox::information(this, tr("Error"), "No hay imagen activa");
	}
	filtroVentana.hide();
}

void VO::ventanaMovil() {
	VentanaMovil vm(this);

	VentanaImagen * actual = (VentanaImagen *) ui.mdiArea->activeSubWindow();
	if (actual != NULL) {
		if (vm.exec()) {
			Imagen * nueva = new Imagen(actual->getImagen()->getQImage(),
					QString::number(contador));
			int f, c;
			vm.size(f, c);
			switch (vm.tipo()) {
			case 0: {
				nueva->aplicarFiltroModa(f, c);
			}
				break;
			case 1: {
				nueva->aplicarFiltroMediana(f, c);
			}
				break;
			case 2: {
				int k;
				vm.getK(k);
				nueva->aplicarFiltroKVecinos(f, c, k);
			}
				break;
			}
			addImage(nueva);
		}
	} else {
		QMessageBox::information(this, tr("Error"), "No hay imagen activa");
	}

}

void VO::espejoHorizontal() {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			Imagen * nueva = TransGeometrica::espejoHorizontal(
					actual->getImagen()->getQImage());
			nueva->setTitle(QString::number(contador));
			nueva->actualizar();
			addImage(nueva);
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}
}

void VO::espejoVertical() {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			Imagen * nueva = TransGeometrica::espejoVertical(
					actual->getImagen()->getQImage());
			nueva->setTitle(QString::number(contador));
			nueva->actualizar();
			addImage(nueva);
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}

}

void VO::transpuesta() {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			Imagen * nueva = TransGeometrica::transpuesta(
					actual->getImagen()->getQImage());
			nueva->setTitle(QString::number(contador));
			nueva->actualizar();
			addImage(nueva);
		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}

}

void VO::zoom() {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {

			ZoomVentana zv(actual->getImagen()->getQImage().size());
			if (zv.exec()) {
				//Recupera los parametros
				int w, h;
				bool bi;
				zv.parametros(w, h, bi);

				//Realiza la transformación
				Imagen * nueva = TransGeometrica::zoom(
						actual->getImagen()->getQImage(), w, h, bi);
				nueva->setTitle(QString::number(contador));
				nueva->actualizar();
				addImage(nueva);
			}

		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}
}

void VO::rotar() {
	try {
		VentanaImagen * actual =
				(VentanaImagen *) ui.mdiArea->activeSubWindow();
		if (actual != NULL) {
			RotarVentana rv;
			if (rv.exec()) {
				//Recupera los parametros
				double angulo;
				bool directa, bi;
				rv.parametros(angulo, directa, bi);

				//Realiza la transformación
				Imagen * nueva;
				if (directa) {
					nueva = TransGeometrica::rotacionD(
							actual->getImagen()->getQImage(), angulo);
				} else {
					nueva = TransGeometrica::rotacionI(
							actual->getImagen()->getQImage(), angulo, bi);
				}

				nueva->setTitle(QString::number(contador));
				nueva->actualizar();
				addImage(nueva);
			}

		} else {
			throw QString::fromUtf8("No hay imagen activa");
		}
	} catch (QString msg) {
		QMessageBox::information(this, tr("Error"), msg);
	}
}

void VO::girar90() {
    try {
        VentanaImagen * actual =
                (VentanaImagen *) ui.mdiArea->activeSubWindow();
        if (actual != NULL) {
		Imagen * nueva = TransGeometrica::girar90(actual->getImagen()->getQImage());
		nueva->setTitle(QString::number(contador));
		nueva->actualizar();
		addImage(nueva);
        } else {
            throw QString::fromUtf8("No hay imagen activa");
        }
    } catch (QString msg) {
        QMessageBox::information(this, tr("Error"), msg);
    }
}

void VO::girar180() {
    try {
        VentanaImagen * actual =
                (VentanaImagen *) ui.mdiArea->activeSubWindow();
        if (actual != NULL) {
		Imagen * nueva = TransGeometrica::girar180(actual->getImagen()->getQImage());
		nueva->setTitle(QString::number(contador));
		nueva->actualizar();
		addImage(nueva);
        } else {
            throw QString::fromUtf8("No hay imagen activa");
        }
    } catch (QString msg) {
        QMessageBox::information(this, tr("Error"), msg);
    }
}

void VO::girar270() {
    try {
        VentanaImagen * actual =
                (VentanaImagen *) ui.mdiArea->activeSubWindow();
        if (actual != NULL) {
		Imagen * nueva = TransGeometrica::girar270(actual->getImagen()->getQImage());
		nueva->setTitle(QString::number(contador));
		nueva->actualizar();
		addImage(nueva);
        } else {
            throw QString::fromUtf8("No hay imagen activa");
        }
    } catch (QString msg) {
        QMessageBox::information(this, tr("Error"), msg);
    }
}
